package gorm

import (
	"github.com/jinzhu/gorm"
	"github.com/pkg/errors"
	"reflect"
	"strings"
)

func Query(db *gorm.DB, where interface{}) (*gorm.DB, error) {
	var err error
	t := reflect.TypeOf(where).Kind()
	if t == reflect.Struct || t == reflect.Map {
		db = db.Where(where)
	} else if t == reflect.Slice {
		for _, item := range where.([]interface{}) { //遍历最外面一层 []interface
			item, ok := item.([]interface{})
			if !ok {
				return nil, errors.New("类型转换错误")
			}
			column := item[0] //取第二层 []interface中的第一个参数 也就是数据库中的字段名或者sql语句 例："id" 或 "id = ?"
			if reflect.TypeOf(column).Kind() == reflect.String {
				count := len(item) //如果第二层 []interface 中只有一个参数 直接写入 sql
				columnStr := column.(string)
				if count == 1 {
					db = db.Where(columnStr)
					continue
				}

				//判断  例"id"或"id = ?"  中有没有"?"
				if strings.Index(columnStr, "?") > -1 { //1.如果有  where语句就直接形成，例 .Where("id = ? and sid = ?",1,2)
					db = db.Where(columnStr, item[1:]...)
				} else { //2.如果没有
					cond := "and"
					opt := "="
					_opt := "="
					var val interface{}
					if count == 2 {
						opt = "="
						val = item[1]
					} else {
						opt = strings.ToLower(item[1].(string))
						_opt = " " + strings.ReplaceAll(opt, " ", "") + " "
						val = item[2]
					}

					if count == 4 {
						cond = strings.ToLower(strings.ReplaceAll(item[3].(string), " ", ""))
					}

					if strings.Index(" in ", _opt) > -1 {
						column = columnStr + " " + opt + " (?)"
					} else if strings.Index(" notin ", _opt) > -1 {
						column = columnStr + " not in (?)"
					} else if strings.Index("= < > <= >= <> != <=> like likebinary notlike ilike rlike regexp notregexp", _opt) > -1 {
						column = columnStr + " " + opt + " ?"
					}

					if cond == "and" {
						db = db.Where(column, val)
					} else {
						db = db.Or(column, val)
					}

				}

			} else if reflect.TypeOf(column).Kind() == reflect.Map {
				db = db.Where(column)
			} else {
				db, err = Query(db, item)
				if err != nil {
					return nil, err
				}
			}
		}
	} else {
		return nil, errors.New("传输类型错误")
	}

	return db, nil
}
